using System;
using System.Collections.Generic;
using System.Drawing;
using Infragistics.UltraChart.Resources.Appearance;
using PluginFrame;

namespace PcrDataAnalysis
{
	public class QuantitativeAnalysis : QualitativeAnalysis
	{
		protected double mDefaultMaxLinearityValue;

		protected IPcrCell mCurrentPcrCell;

		protected int mCurrentChannelIndex;

		protected bool mIsFindMultipleCell;

		protected IStandardCurveConfiguration mStandardCurveConfiguration;

		protected string[] mDetectionTypeString;

		public QuantitativeAnalysis(IApplication application)
			: base(application)
		{
			mStandardCurveConfiguration = mConfigurationService.StandardCurveConfiguration;
			mDetectionTypeString = mConfigurationService.GetDetectionTypeArray(PcrSystemType.AbsoluteAnalysis);
		}

		private void SetCellConclusion(List<IPcrCell> pcrCells, int channelIndex, IQuantitativeAnalysisResult analysisResult, IAbsoluteProjectProperty property)
		{
			double quantitativeThreshold = property.QuantitativeThreshold;
			bool isSetQuantitativeGreyZone = property.IsSetQuantitativeGreyZone;
			double quantitativeGreyZone = property.QuantitativeGreyZone;
			foreach (IPcrCell pcrCell in pcrCells)
			{
				double result = double.NaN;
				string cellInformation = pcrCell.GetCellInformation("MeasurementResultKey", channelIndex);
				string cellInformation2 = pcrCell.GetCellInformation("AverageConcentrationKey", channelIndex);
				try
				{
					if (string.IsNullOrEmpty(cellInformation2))
					{
						if (!double.TryParse(cellInformation, out result))
						{
							result = double.NaN;
						}
					}
					else if (!double.TryParse(cellInformation2, out result))
					{
						result = double.NaN;
					}
				}
				catch (Exception)
				{
					result = double.NaN;
				}
				if (string.IsNullOrEmpty(pcrCell.Project.QuantitativeNegativeConlusion))
				{
					pcrCell.Project.QuantitativeNegativeConlusion = mResourceManager.GetString("NegativeString");
				}
				if (string.IsNullOrEmpty(pcrCell.Project.QuantitativePositiveConlusion))
				{
					pcrCell.Project.QuantitativePositiveConlusion = mResourceManager.GetString("PositiveString");
				}
				if (double.IsNaN(result))
				{
					if (analysisResult.PcrExperimentStatus == PcrExperimentStatus.AnalysisFailed)
					{
						pcrCell.SetCellInformation("InterpretationKey", channelIndex, cellInformation);
						pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, Color.Black.ToArgb().ToString());
					}
					else
					{
						pcrCell.SetCellInformation("MeasurementResultKey", channelIndex, "<" + quantitativeThreshold);
						pcrCell.SetCellInformation("InterpretationKey", channelIndex, pcrCell.Project.QuantitativeNegativeConlusion);
						pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, pcrCell.Project.QuantitativeNegativeColor.ToArgb().ToString());
					}
				}
				else if (result < quantitativeThreshold)
				{
					pcrCell.SetCellInformation("MeasurementResultKey", channelIndex, "<" + quantitativeThreshold);
					pcrCell.SetCellInformation("InterpretationKey", channelIndex, pcrCell.Project.QuantitativeNegativeConlusion);
					pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, pcrCell.Project.QuantitativeNegativeColor.ToArgb().ToString());
				}
				else if (isSetQuantitativeGreyZone)
				{
					if (result < quantitativeGreyZone)
					{
						if (string.IsNullOrEmpty(pcrCell.Project.QuantitativeGreyConlusion))
						{
							pcrCell.Project.QuantitativeGreyConlusion = mResourceManager.GetString("ReTestString");
						}
						pcrCell.SetCellInformation("InterpretationKey", channelIndex, pcrCell.Project.QuantitativeGreyConlusion);
						pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, pcrCell.Project.QuantitativeGreyColor.ToArgb().ToString());
					}
					else
					{
						pcrCell.SetCellInformation("InterpretationKey", channelIndex, pcrCell.Project.QuantitativePositiveConlusion);
						pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, pcrCell.Project.QuantitativePositiveColor.ToArgb().ToString());
					}
				}
				else
				{
					pcrCell.SetCellInformation("InterpretationKey", channelIndex, pcrCell.Project.QuantitativePositiveConlusion);
					pcrCell.SetCellInformation("InterpretationColorKey", channelIndex, pcrCell.Project.QuantitativePositiveColor.ToArgb().ToString());
				}
			}
		}

		public override AnalysisError Execute(Dictionary<string, List<IPcrCell>> projectCells, IPcrExperiment pcrExperiment, IAbsoluteAnalysisParameterConfiguration analysisOption, IMeltingAnalysisParameterConfiguration meltingOption)
		{
			try
			{
				AnalysisParameterConfiguration analysisParameterConfiguration = analysisOption as AnalysisParameterConfiguration;
				int projectChannel = analysisParameterConfiguration.ProjectChannel;
				IBaseLineNormalization baseLineNormalization = new NormalizationCreator().Creator(mApplication, analysisOption.BaselineOptimization);
				IQuantitativeAnalysisResult quantitativeAnalysisResult = new QuantitativeAnalysisResult();
				quantitativeAnalysisResult.ProjectChannel = projectChannel;
				quantitativeAnalysisResult.ProjectName = (analysisOption as AnalysisParameterConfiguration).ProjectName;
				quantitativeAnalysisResult.PcrExperimentStatus = PcrExperimentStatus.AccomplishedSaved;
				pcrExperiment.SetAnalysisResult(analysisOption.Project, projectChannel, analysisParameterConfiguration.TargetIndex, quantitativeAnalysisResult);
				List<IPcrCell> sameTypeCells = GetSameTypeCells(projectCells, mDetectionTypeString[0], true);
				List<IPcrCell> sameTypeCells2 = GetSameTypeCells(projectCells, mDetectionTypeString[0], false);
				bool flag = false;
				double num = 0.0;
				int num2 = 0;
				string value = string.Empty;
				foreach (IPcrCell item in sameTypeCells)
				{
					string cellInformation = item.GetCellInformation("PropertyKey", projectChannel);
					if (!cellInformation.Equals(value))
					{
						num2++;
						value = cellInformation;
						if (num2 >= mAnalysisConfiguration.MinStandardCellCount)
						{
							break;
						}
					}
				}
				IPcrStandardCurve pcrStandardCurve = null;
				if (num2 < mAnalysisConfiguration.MinStandardCellCount)
				{
					pcrStandardCurve = analysisOption.ImportedStandardCurve;
					if (pcrStandardCurve == null)
					{
						flag = true;
						num = analysisOption.ManualThreshold;
						CalculateCellsCycleValue(sameTypeCells, pcrExperiment, analysisOption, num, baseLineNormalization, meltingOption);
						quantitativeAnalysisResult.StandardPointSeries = null;
						quantitativeAnalysisResult.StandardPointSeries = null;
						quantitativeAnalysisResult.PcrExperimentStatus = PcrExperimentStatus.AnalysisFailed;
					}
					else
					{
						List<IPcrCell> standardPcrCells = pcrStandardCurve.GetStandardPcrCells(projectChannel, analysisParameterConfiguration.TargetIndex);
						if (standardPcrCells == null || standardPcrCells.Count <= 0)
						{
							flag = true;
							num = analysisOption.ManualThreshold;
							CalculateCellsCycleValue(sameTypeCells, pcrExperiment, analysisOption, num, baseLineNormalization, meltingOption);
							quantitativeAnalysisResult.PcrExperimentStatus = PcrExperimentStatus.AnalysisFailed;
						}
						else
						{
							num = CalculateStandardCurve(standardPcrCells, pcrExperiment, analysisOption, baseLineNormalization, analysisParameterConfiguration.TargetIndex);
						}
					}
				}
				else
				{
					num = CalculateStandardCurve(sameTypeCells, pcrExperiment, analysisOption, baseLineNormalization, analysisParameterConfiguration.TargetIndex);
				}
				IAbsoluteProjectProperty absoluteProjectProperty = analysisParameterConfiguration.ProjectProperty as IAbsoluteProjectProperty;
				if (absoluteProjectProperty == null)
				{
					analysisParameterConfiguration.ProjectProperty = mConfigurationService.CreateAbsoluteProjectProperty(analysisParameterConfiguration.ProjectName, string.Empty, mConfigurationService.QuantitativeThreshold, mConfigurationService.QualitativeThreshold, mConfigurationService.QualitativeResultUnit, mConfigurationService.QuantitativeResultUnit, false, false, 0.0, 0.0);
					absoluteProjectProperty = analysisParameterConfiguration.ProjectProperty as IAbsoluteProjectProperty;
				}
				CalculateCellsCycleValue(sameTypeCells2, pcrExperiment, analysisOption, num, baseLineNormalization, meltingOption);
				List<IPcrCell> list = new List<IPcrCell>();
				list.AddRange(sameTypeCells);
				list.AddRange(sameTypeCells2);
				CalculateCellConcentration(list, quantitativeAnalysisResult, absoluteProjectProperty);
				mIsFindMultipleCell = false;
				CalculateMultiCells(sameTypeCells, projectChannel, FindStandardMultiCell);
				List<IPcrCell> pcrCells = sameTypeCells2.FindAll(FindControlCell);
				CalculateMultiCells(pcrCells, projectChannel, FindStandardMultiCell);
				List<IPcrCell> pcrCells2 = sameTypeCells2.FindAll(FindSampleCell);
				CalculateMultiCells(pcrCells2, projectChannel, FindSampleMultiCell);
				List<IPcrCell> pcrCells3 = sameTypeCells2.FindAll(FindNTCCell);
				CalculateMultiCells(pcrCells3, projectChannel, FindSampleMultiCell);
				List<IPcrCell> pcrCells4 = sameTypeCells2.FindAll(FindNegativeCell);
				CalculateMultiCells(pcrCells4, projectChannel, FindSampleMultiCell);
				List<IPcrCell> pcrCells5 = sameTypeCells2.FindAll(FindPositiveCell);
				CalculateMultiCells(pcrCells5, projectChannel, FindSampleMultiCell);
				SetCellConclusion(list, projectChannel, quantitativeAnalysisResult, absoluteProjectProperty);
				RefreshResultColumns(pcrExperiment, projectChannel);
				analysisParameterConfiguration.IsNeedReAnalysis = false;
				if (!flag)
				{
					return AnalysisError.NA;
				}
				return AnalysisError.LessStandard;
			}
			catch (Exception)
			{
				throw;
			}
		}

		private void RefreshResultColumns(IPcrExperiment pcrExperiment, int channelIndex)
		{
		}

		protected bool CreateStandardCuveSeries(IQuantitativeAnalysisResult analysisResult, int channelIndex, List<double> cellConcentrations, List<double> cellcycles, List<int> cellIDs)
		{
			if (cellConcentrations.Count > 1)
			{
				XYSeries xYSeries = new XYSeries();
				xYSeries.Key = analysisResult.ProjectName + "StandardPoint" + channelIndex;
				xYSeries.PEs.Clear();
				xYSeries.PEs.Add(new PaintElement(mStandardCurveConfiguration.PointColor));
				for (int i = 0; i < cellConcentrations.Count; i++)
				{
					xYSeries.Points.Add(new XYDataPoint(cellConcentrations[i], cellcycles[i], cellIDs[i].ToString(), false));
				}
				XYSeries xYSeries2 = new XYSeries();
				xYSeries2.Key = analysisResult.ProjectName + "StandardLine" + channelIndex;
				xYSeries2.PEs.Clear();
				xYSeries2.PEs.Add(new PaintElement(mStandardCurveConfiguration.LineColor));
				double[] array = new double[2];
				double[] array2 = new double[2];
				double xMinimum = xYSeries.GetXMinimum();
				double xMaximum = xYSeries.GetXMaximum();
				array[0] = ((xMinimum <= 0.0) ? xMinimum : (xMinimum - 1.0));
				array[1] = analysisResult.Slope * array[0] + analysisResult.Intercept;
				array2[0] = xMaximum + 1.0;
				array2[1] = analysisResult.Slope * array2[0] + analysisResult.Intercept;
				xYSeries2.Points.Add(new XYDataPoint(array[0], array[1], string.Empty, false));
				xYSeries2.Points.Add(new XYDataPoint(array2[0], array2[1], string.Empty, false));
				xYSeries2.Visible = false;
				xYSeries.Visible = false;
				analysisResult.StandardLineSeries = xYSeries2;
				analysisResult.StandardPointSeries = xYSeries;
				return true;
			}
			analysisResult.StandardLineSeries = null;
			analysisResult.StandardPointSeries = null;
			return false;
		}

		protected double CalculateStandardCurve(List<IPcrCell> standardCells, IPcrExperiment pcrExperiment, IAbsoluteAnalysisParameterConfiguration analysisOption, IBaseLineNormalization baseLineNormalization, int targetIndex)
		{
			if (standardCells.Count < mAnalysisConfiguration.MinStandardCellCount)
			{
				return analysisOption.ManualThreshold;
			}
			int projectChannel = (analysisOption as AnalysisParameterConfiguration).ProjectChannel;
			double num;
			double num2;
			if (!analysisOption.IsAutoThreshold)
			{
				num = analysisOption.ManualThreshold;
				num2 = num;
			}
			else
			{
				num = mAnalysisConfiguration.AutoThresholdStartValue;
				num2 = mAnalysisConfiguration.AutoThresholdStopValue;
			}
			double autoThresholdInterval = mAnalysisConfiguration.AutoThresholdInterval;
			List<List<double>> list = new List<List<double>>();
			List<double> list2 = new List<double>();
			List<double> list3 = new List<double>();
			List<double> list4 = new List<double>();
			List<double> list5 = new List<double>();
			new List<double>();
			for (int i = 0; i < standardCells.Count; i++)
			{
				baseLineNormalization.Execute(standardCells[i], analysisOption, projectChannel, true);
				standardCells[i].InitializeAmplificationCurveSeries(projectChannel);
				standardCells[i].AddPointToRawCurve(projectChannel, false, 0);
				standardCells[i].IsSetInterpResult = false;
				list5.Add(Math.Log10(Convert.ToDouble(standardCells[i].GetCellInformation("PropertyKey", projectChannel))));
			}
			for (double num3 = num; num3 <= num2; num3 += autoThresholdInterval)
			{
				List<double> list6 = new List<double>();
				List<double> list7 = new List<double>();
				for (int j = 0; j < standardCells.Count; j++)
				{
					double num4 = CalculateLightDataInterp(standardCells[j], projectChannel, num3);
					if (num4 > 0.0 && num4 <= (double)standardCells[j].AmplificationStopCycle)
					{
						list6.Add(num4);
						list7.Add(num4);
					}
					else
					{
						list6.Add(double.NaN);
						list7.Add(double.NaN);
					}
				}
				double slope = 0.0;
				double intercept = 0.0;
				double linearity = 0.0;
				mMiscService.CalculateLineLeastSquare(list5.ToArray(), list6.ToArray(), ref slope, ref intercept, ref linearity);
				list2.Add(slope);
				list3.Add(intercept);
				list4.Add(linearity);
				list.Add(list7);
			}
			mDefaultMaxLinearityValue = list4[0];
			int num5 = 0;
			for (int k = 0; k < list4.Count; k++)
			{
				if (Math.Abs(list4[k]) > Math.Abs(mDefaultMaxLinearityValue))
				{
					num5 = k;
					mDefaultMaxLinearityValue = list4[k];
				}
			}
			IQuantitativeAnalysisResult quantitativeAnalysisResult = pcrExperiment.GetAnalysisResult(analysisOption.Project, projectChannel, targetIndex) as IQuantitativeAnalysisResult;
			quantitativeAnalysisResult.Slope = list2[num5];
			quantitativeAnalysisResult.Intercept = list3[num5];
			quantitativeAnalysisResult.SquareError = list4[num5];
			if (quantitativeAnalysisResult.Intercept != 0.0)
			{
				quantitativeAnalysisResult.AmplificationRate = Math.Pow(10.0, -1.0 / quantitativeAnalysisResult.Slope) - 1.0;
			}
			else
			{
				quantitativeAnalysisResult.AmplificationRate = 0.0;
			}
			quantitativeAnalysisResult.Threshold = num + (double)num5 * autoThresholdInterval;
			analysisOption.ManualThreshold = quantitativeAnalysisResult.Threshold;
			List<double> list8 = new List<double>();
			List<double> list9 = new List<double>();
			List<int> list10 = new List<int>();
			for (int l = 0; l < standardCells.Count; l++)
			{
				double num6 = list[num5][l];
				standardCells[l].SetCycleValue(projectChannel, num6);
				if (mConfigurationService.IsSetCtThreshold && num6 <= (double)mConfigurationService.CtThreshold)
				{
					num6 = double.NaN;
				}
				string value = (double.IsNaN(num6) ? "No Ct" : num6.ToString(mAnalysisConfiguration.CTValueFormatString));
				standardCells[l].SetCellInformation("CycleValueKey", projectChannel, value);
				if (!num6.Equals(double.NaN))
				{
					list8.Add(list5[l]);
					list9.Add(num6);
					list10.Add(standardCells[l].CellID);
				}
			}
			if (CreateStandardCuveSeries(quantitativeAnalysisResult, projectChannel, list8, list9, list10))
			{
				quantitativeAnalysisResult.PcrExperimentStatus = PcrExperimentStatus.AnalysisAccomplished;
			}
			else
			{
				quantitativeAnalysisResult.PcrExperimentStatus = PcrExperimentStatus.AnalysisFailed;
			}
			return quantitativeAnalysisResult.Threshold;
		}

		protected void CalculateCellConcentration(List<IPcrCell> nonBlankCells, IQuantitativeAnalysisResult analysisResult, IAbsoluteProjectProperty projectProperty)
		{
			if (analysisResult == null || projectProperty == null)
			{
				return;
			}
			int projectChannel = analysisResult.ProjectChannel;
			foreach (IPcrCell nonBlankCell in nonBlankCells)
			{
				double cycleValue = nonBlankCell.GetCycleValue(projectChannel);
				if (!double.IsNaN(cycleValue))
				{
					double num = CalculateXValueInLine(analysisResult.Slope, analysisResult.Intercept, cycleValue);
					if (double.IsInfinity(num) || double.IsNaN(num))
					{
						nonBlankCell.SetCellInformation("MeasurementResultKey", projectChannel, mResourceManager.GetString("NoResultString"));
					}
					else
					{
						nonBlankCell.SetCellInformation("MeasurementResultKey", projectChannel, Math.Pow(10.0, num).ToString(mAnalysisConfiguration.ConcentrationFormatString));
					}
				}
				else
				{
					nonBlankCell.SetConcentration(projectChannel, double.NaN);
					nonBlankCell.SetCellInformation("MeasurementResultKey", projectChannel, mResourceManager.GetString("NoResultString"));
				}
				nonBlankCell.SetIsNeedReAnalysis(projectChannel, false);
			}
		}

		protected double CalculateXValueInLine(double slope, double intercept, double yValue)
		{
			return (yValue - intercept) / slope;
		}

		private void CalculateMultiCellConcentration(List<IPcrCell> pcrCells, int channelIndex)
		{
			if (pcrCells.Count == 0)
			{
				return;
			}
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			bool flag = false;
			foreach (IPcrCell pcrCell in pcrCells)
			{
				double cycleValue = pcrCell.GetCycleValue(channelIndex);
				string cellInformation = pcrCell.GetCellInformation("MeasurementResultKey", channelIndex);
				if (!double.IsNaN(cycleValue) && !cellInformation.Equals(mResourceManager.GetString("NoResultString")))
				{
					try
					{
						num += Convert.ToDouble(cellInformation);
					}
					catch (Exception)
					{
						flag = true;
						break;
					}
					num2 += cycleValue;
					num3 += 1.0;
					continue;
				}
				flag = true;
				break;
			}
			if (num3 <= 0.0)
			{
				flag = true;
			}
			if (flag)
			{
				return;
			}
			double num4 = num / num3;
			double num5 = num2 / num3;
			string value = num4.ToString(mAnalysisConfiguration.ConcentrationFormatString);
			double num6 = 0.0;
			foreach (IPcrCell pcrCell2 in pcrCells)
			{
				double cycleValue2 = pcrCell2.GetCycleValue(channelIndex);
				if (!double.IsNaN(cycleValue2))
				{
					num6 += Math.Pow(cycleValue2 - num5, 2.0);
				}
				pcrCell2.SetCellInformation("AverageConcentrationKey", channelIndex, value);
			}
			string value2 = (Math.Sqrt(num6 / (num3 - 1.0)) / num5 * 100.0).ToString(mAnalysisConfiguration.CTValueFormatString);
			foreach (IPcrCell pcrCell3 in pcrCells)
			{
				pcrCell3.SetCellInformation("CVValueKey", channelIndex, value2);
				pcrCell3.SetCellInformation("LightCVKey", channelIndex, value2);
				pcrCell3.SetMultiCellList(channelIndex, pcrCells);
			}
		}

		private void CalculateMultiCells(List<IPcrCell> pcrCells, int channelIndex, Predicate<IPcrCell> findMultiCells)
		{
			int num = 0;
			if (pcrCells == null || pcrCells.Count == 0)
			{
				return;
			}
			do
			{
				mCurrentPcrCell = pcrCells[num];
				mCurrentChannelIndex = channelIndex;
				List<IPcrCell> list = pcrCells.FindAll(findMultiCells);
				if (list == null)
				{
					break;
				}
				if (list.Count > 1)
				{
					mIsFindMultipleCell = true;
					CalculateMultiCellConcentration(list, channelIndex);
					foreach (IPcrCell item in list)
					{
						pcrCells.Remove(item);
					}
				}
				else
				{
					num++;
				}
			}
			while (num < pcrCells.Count);
		}

		private bool FindControlCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(mDetectionTypeString[5]) == 0;
		}

		private bool FindSampleCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(mDetectionTypeString[1]) == 0;
		}

		private bool FindNTCCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(mDetectionTypeString[4]) == 0;
		}

		private bool FindNegativeCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(mDetectionTypeString[2]) == 0;
		}

		private bool FindPositiveCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(mDetectionTypeString[3]) == 0;
		}

		private bool FindStandardMultiCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("PropertyKey", mCurrentChannelIndex);
			string cellInformation2 = mCurrentPcrCell.GetCellInformation("PropertyKey", mCurrentChannelIndex);
			return cellInformation.CompareTo(cellInformation2) == 0;
		}

		private bool FindSampleMultiCell(IPcrCell pcrCell)
		{
			string cellInformation = pcrCell.GetCellInformation("ReplicatedTubeKey", mCurrentChannelIndex);
			string cellInformation2 = mCurrentPcrCell.GetCellInformation("ReplicatedTubeKey", mCurrentChannelIndex);
			if (cellInformation2.Length > 0)
			{
				return cellInformation.CompareTo(cellInformation2) == 0;
			}
			return false;
		}
	}
}
